package ar.edu.itba.it.pdc.httpParser.models;

import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;

import ar.edu.itba.it.pdc.httpParser.interfaces.Model;
import ar.edu.itba.it.pdc.nio.ByteBufferPool;
import ar.edu.itba.it.pdc.nio.MemoryAllocationLimitHited;

public class HttpHeaders implements Model {
	
	private Map<String, HttpHeader> headersMap = new HashMap<String, HttpHeader>();

	private final String[] singleValueHeaders = {

        "Age",
        "Content-Length",
        "Content-Location",
        "Content-Md5",
        "Content-Range",
        "Content-Type",
        "Date",
        "Etag",
        "Expires",
        "From",
        "Host",
        "If-Modified-Since",
        "If-Range",
        "If-Unmodified-Since",
        "Last-Modified",
        "Location",
        "Max-Forwards",
        "Referer",
        "Retry-After",
	};
	
	private final List<String> singleValueHeadersList; 
	
	public HttpHeaders() {
		singleValueHeadersList = new LinkedList<String>();
		for(String headerName: singleValueHeaders) {
			singleValueHeadersList.add(headerName.toUpperCase());
		}
	}
	
	
	public void put(List<Token> headerName, List<Token> headerValue) {
		String name = "";
		for (Token t : headerName) {
			name += t.toString().toUpperCase();
		}
		if (!headersMap.containsKey(name)) {
			headersMap.put(name, new HttpHeader(headerName, headerValue));
		} else if (!singleValueHeadersList.contains(name)) {
			HttpHeader header = headersMap.get(name);
			headerValue.add(0, new Token(","));
			header.add(headerValue);
			headersMap.put(name, header);			
		}
		
	}
	

	public void put(String name, String value) {
		headersMap.put(name.toUpperCase(), new HttpHeader(name, value));
	}
	

	public String getHeader(String headerName) {
		HttpHeader header = headersMap.get(headerName.toUpperCase());
		if (header == null) {
			return null;
		}
		return header.getValue().trim();
	}
	
	public boolean removeHeader(String headerName){
		return headersMap.remove(headerName.toUpperCase())!=null;
	}

	public void appendByteBuffers(Queue<ByteBuffer> queue) throws MemoryAllocationLimitHited {

		for (String headerName: headersMap.keySet()) {
			HttpHeader header = headersMap.get(headerName);
			if (!singleValueHeadersList.contains(headerName)) {
				
				String headerValue = header.getValue();
				String [] values = headerValue.split(",");
				for (String value: values) {
					HttpHeader newHeader = new HttpHeader(header.getName(), value);
					newHeader.appendByteBuffers(queue);
				}
			} else {
				header.appendByteBuffers(queue);
			}
			
		}
		
		ByteBuffer byteBuffer  = ByteBufferPool.getInstance().getByteBuffer();
		byteBuffer.put((byte) '\r');
		byteBuffer.put((byte) '\n');
		byteBuffer.flip();
		queue.add(byteBuffer);
	}

}
